#!/bin/bash
# Copyright 2014 - Rackspace Hosting
#
#    Licensed under the Apache License, Version 2.0 (the "License");
#    you may not use this file except in compliance with the License.
#    You may obtain a copy of the License at
#
#        http://www.apache.org/licenses/LICENSE-2.0
#
#    Unless required by applicable law or agreed to in writing, software
#    distributed under the License is distributed on an "AS IS" BASIS,
#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#    See the License for the specific language governing permissions and
#    limitations under the License.


# Common functions for build-app and unittest-app

# Add a timestamp, and log a message to STDOUT and to $LOG.

function TLOG () {
  local MESSAGE="$*"
  if [ ! -z "$MESSAGE" ]; then

    local LOGFILE=${LOG_FILE:-/dev/null}
    local TIMESTAMP=$(date --iso-8601=seconds)
    JSONMESSAGE="{ \"@timestamp\": \"$TIMESTAMP\", \"project_id\": \"$PROJECT_ID\", \"commit_id\": \"$COMMIT_ID\", \"stage_id\": \"$BUILD_ID\", \"task\": \"$TASKNAME\", \"message\": \"$MESSAGE\"}"
    echo $JSONMESSAGE >> $LOGFILE

  fi
}


# Overwrite TLOG to filter for user input.
function TLOG_FILTERED () {
  local MESSAGE="$*"
  if [ ! -z "$MESSAGE" ]; then

    # This is deliberately not a local, as it's to persist between calls to TLOG.
    _USER=${_USER:-false}

    echo "$MESSAGE" | grep -i "drone build results" && _USER=false

    local LOGFILE=${LOG_FILE:-/dev/null}
    local TIMESTAMP=$(date --iso-8601=seconds)
    JSONMESSAGE="{ \"@timestamp\": \"$TIMESTAMP\", \"project_id\": \"$PROJECT_ID\", \"commit_id\": \"$COMMIT_ID\", \"stage_id\": \"$BUILD_ID\", \"task\": \"$TASKNAME\", \"message\": \"$MESSAGE\", \"_user\": \"$_USER\" }"
    echo $JSONMESSAGE >> $LOGFILE

    echo "$MESSAGE" | grep -i "starting build" && _USER=true

    export _USER

  fi
}


# Build the logfile name, and ensure it exists.
function GET_LOGFILE () {
  local LOG_DIR=${SOLUM_TASK_DIR:-/dev/null}
  if [ "$LOG_DIR" != "/dev/null" ]; then
    sudo mkdir -p "$LOG_DIR"
    sudo chmod a+w "$LOG_DIR"
  fi

  local LOG_FILE=/dev/null
  if [ "$LOG_DIR" != "/dev/null" ]; then
    LOG_FILE="$LOG_DIR/$TASKNAME-$BUILD_ID.log"
    touch $LOG_FILE
  fi

  echo $LOG_FILE
}

# Get time elapsed since $1.
function elapsed () {
  local START=$1
  local NOW=$(date +"%s")
  expr $NOW - $START
}

# Profile and run a command, and return its exit code.
function PRUN () {
  # If the first argument is "silent", then set a flag and shift.
  local SILENT=false
  if [ "$1" == "silent" ]; then
    SILENT=true
    shift
  fi

  local CMD="$*"
  local LOGFILE=${LOG:-/dev/null}

  if $SILENT; then
    LOGFILE=/dev/null
  fi

  if ! $SILENT; then
    TLOG Starting: $CMD
  fi
  local EXIT_STATUS
  local START=$(date +"%s")
  if $SILENT; then
    $CMD 2>&1 >> /dev/null; test ${PIPESTATUS[0]} -eq 0
    EXIT_STATUS=$?
  else
    TLOG Starting: $CMD
    $CMD 2>&1 > >(while read LINE; do TLOG $LINE; done)
    EXIT_STATUS=$?
  fi

  local ELAPSED=$(elapsed $START)
  local SUCCESS
  [ $EXIT_STATUS -eq 0 ] && SUCCESS="Finished" || SUCCESS="FAILED"

  if ! $SILENT; then
    TLOG $SUCCESS: $CMD "[Elapsed: $ELAPSED sec] (EXIT_STATUS=$EXIT_STATUS)"
  fi

  return $EXIT_STATUS
}

# Register ssh private key with ssh-agent.
# SSH_AUTH_SOCK env variable will be unique to this process and
# it restricts other apps to access current ssh credentials.
function add_ssh_creds () {
  local SSH_PRIVATE_KEY=$1
  local APP_DIR=$2

  if [ -n "$SSH_PRIVATE_KEY" ]; then
    eval `ssh-agent -s`
    SSH_PRIVATE_KEY_FILE=$APP_DIR/.creds
    echo "$SSH_PRIVATE_KEY" > $SSH_PRIVATE_KEY_FILE
    chmod 600 $SSH_PRIVATE_KEY_FILE
    ssh-add $SSH_PRIVATE_KEY_FILE ; EXIT_STATUS=$?
    rm -f $SSH_PRIVATE_KEY_FILE
    ssh -o StrictHostKeyChecking=no git@github.com
    return $EXIT_STATUS
  else
    return 0
  fi
}

# De-register ssh private key with ssh-agent.
function remove_ssh_creds () {
  local SSH_PRIVATE_KEY=$1

  if [ -n "$SSH_PRIVATE_KEY" ]; then
    ssh-agent -k
  fi
}

function test_public_repo () {
    local GIT_REPO=$1
    if [[ -z $GIT_PRIVATE_KEY ]]; then
        curl -If ${GIT_REPO%%.git} > /dev/null 2>&1
        return $?
    fi
    return 0
}

function git_clone_with_retry () {
  local GIT_REPO=$1
  local DESTINATION=$2
  shift; shift
  local SINGLEBRANCH=$1

  RETRIES=0
  until [ $RETRIES -ge 5 ]; do
    rm -rf $DESTINATION
    PRUN git clone $SINGLEBRANCH $GIT_REPO $DESTINATION && return 0
    RETRIES=$[$RETRIES+1]
    sleep 5
  done
  return 1
}

function git_clone_with_commit_sha_retry () {
  local GIT_REPO=$1
  local DESTINATION=$2
  local COMMIT_SHA=$3

  RETRIES=0
  until [ $RETRIES -ge 5 ]; do
    rm -rf $DESTINATION
    PRUN git clone $GIT_REPO $DESTINATION;cd  $DESTINATION; git checkout $COMMIT_SHA;cd - && return 0
    RETRIES=$[$RETRIES+1]
    sleep 5
  done
  return 1
}

function glance_upload_with_retry () {
  local DU_IMG_TAG=$1
  shift
  sudo docker save "$DU_IMG_TAG" | glance --os-image-api-version 2 --os-auth-token $OS_AUTH_TOKEN image-create --container-format=docker --disk-format=raw --name "$DU_IMG_TAG" >& /dev/null  && return 0
  sleep 2
  sudo docker save "$DU_IMG_TAG" | glance --os-image-api-version 2 --os-auth-token $OS_AUTH_TOKEN image-create --container-format=docker --disk-format=raw --name "$DU_IMG_TAG" >& /dev/null
}

function docker_build_with_retry () {
  local APP_NAME=$1
  local DESTINATION=$2
  shift; shift
  PRUN sudo docker build --force-rm=true -t $APP_NAME $DESTINATION && return 0
  sleep 2
  PRUN sudo docker build --no-cache --force-rm=true -t $APP_NAME $DESTINATION
}

function docker_load_with_retry () {
  local FILE=$1
  shift
  sudo docker load -i $FILE && return 0
  sleep 1
  sudo docker load -i $FILE
}

function docker_save_with_retry () {
  local OUTPUT_FILE=$1
  shift
  local DOCKER_IMG=$1

  sudo docker save --output $OUTPUT_FILE $DOCKER_IMG && return 0
  sleep 1
  sudo docker save --output $OUTPUT_FILE $DOCKER_IMG
}
